import React from 'react';
import './index.scss';
import { Form, Input, Button, message, Image, Modal } from 'antd';
import { UserOutlined, KeyOutlined, SafetyOutlined } from '@ant-design/icons';
import { getSmsCode, getSysUserInfo, login, loginSms } from 'admin/servers/servers';
import { v4 as uuidv4 } from 'uuid';
import { buildMenuPermissionMgr } from 'permission/Index';
import { getStore } from 'store/store';
import { FormInstance } from 'antd/lib/form';
import { LoginResponse } from 'admin/schema/User';
import { checkValidate, encryptStr } from 'utils/tools';
import { initSocket } from 'servers/socket';
import {
  setSystemConfigAsynic,
  setToken,
  setUserInfoLater,
  setLoginInfo,
  setUserInfo,
} from 'store/root/action';
import { connect } from 'react-redux';
import { JSONObject } from '../../schema/common';
import { RouteConfigComponentProps } from 'react-router-config';
import { logoutSys, LOGIN_TYPE_SMS } from 'utils';
import { debounce } from 'lodash';

/**
 * 登录模块维护的state
 */
interface LoginState {
  // 登录按钮状态
  loading: boolean;
  // 当前验证码随机uuid
  codeId: string;
  // 验证码图片
  codeImg: string;
  // 是否展示
  show: boolean;
  // 检查图形验证码是否必填
  checkCode: boolean;
  // 检查短信验证码是否必填
  checkSms: boolean;
  // 验证码发送中
  smsLoading: boolean;
  // 短信验证码获取按钮状态-1-获取验证码，2-重发，0-重发倒计时（禁用状态）
  smsBtnActive: 1 | 2 | 0;
  // 倒计时-60秒
  count: number;
  showSmsCodeCheck: boolean; // 是否展示短信验证码
}

/**
 * 系统登录页-最新-唯一-合并版
 * 包含：短信验证码登录方式和普通登录方式
 */
class LoginSms extends React.Component<{}, LoginState> {
  // 登录form的表单引用
  form: React.RefObject<FormInstance>;
  smsForm: React.RefObject<FormInstance>;

  constructor(prop: {}) {
    super(prop);
    this.form = React.createRef();
    this.smsForm = React.createRef();
    this.state = {
      loading: false,
      codeId: uuidv4(),
      codeImg: '',
      show: false,
      checkCode: true,
      checkSms: false,
      smsLoading: false,
      smsBtnActive: 1,
      count: 0,
      showSmsCodeCheck: false,
    };
  }

  componentDidMount() {
    this.checkToken();
    // 初始化网站配置
    (this.props as JSONObject).setSystemConfigAsynic();
    console.log('部署配置信息:');
    console.log('REACT_APP_API_URL   >>>>>>>>>>>>*****', process.env.REACT_APP_API_URL);
    console.log('REACT_APP_SOCKET_URL   >>>>>>>>>*****', process.env.REACT_APP_SOCKET_URL);
    console.log('REACT_APP_DEBUG   >>>>>>>>>*****', process.env.REACT_APP_DEBUG);
    console.log('REACT_APP_LOGIN_STYLE   >>>>>>>>>*****', process.env.REACT_APP_LOGIN_STYLE);
    console.log('REACT_APP_LOGIN_NO_CHECK   >>>>>>>>>*****', process.env.REACT_APP_LOGIN_NO_CHECK);

    //获取域名（如果是ip地址，domain不带端口号）
    const host = window.location.host;
    const domain = document.domain;
    //获取页面完整地址
    const url = window.location.href;
    console.log('获取域名信息:');
    console.log('host=' + host);
    console.log('domain=' + domain);
    console.log('url=' + url);

    let socket_url: any;
    if (!process.env.REACT_APP_SOCKET_URL?.startsWith('ws://')) {
      // 配置不正确，则取域名，拼接
      console.log(1);
      socket_url = 'ws://' + host;
      console.log('REACT_APP_SOCKET_URL--前端拼接>>>*****', socket_url);
    } else {
      // 配置有wss开头
      console.log(2);
      socket_url = process.env.REACT_APP_SOCKET_URL;
      console.log('REACT_APP_SOCKET_URL--部署配置>>>*****', socket_url);
    }
  }
  componentWillUnmount = () => {
    this.setState = (state, callback) => {
      return;
    };
  };

  /**获取短信验证码 */
  private handleSmsCode = debounce(() => {
    this.setState(
      {
        checkCode: true,
        checkSms: false,
      },
      () => {
        (this.form.current as FormInstance).validateFields().then(values => {
          this.setState(
            {
              smsLoading: true,
            },
            async () => {
              getSmsCode({
                account: values.username,
                captcha: values.codeWord,
                captchaId: this.state.codeId,
              })
                .then(res => {
                  // console.log('res', res);
                  if (res.code === 0) {
                    message.warning('短信验证码已发送');
                    this.setState({
                      smsLoading: false,
                      smsBtnActive: 0,
                      count: 60,
                      checkCode: false, // 短信验证码发送成功，取消图形验证码必填校验
                      showSmsCodeCheck: true, // 短信验证码弹窗
                    });
                    const time = setInterval(() => {
                      if (this.state.count <= 0) {
                        clearInterval(time);
                        console.log('重发倒计时结束', this.state.count);
                        this.setState({
                          smsBtnActive: 2,
                        });
                        return;
                      }
                      this.setState({ count: this.state.count - 1 });
                    }, 1000);
                  }
                })
                .catch(error => {
                  console.error(`系统异常: ${JSON.stringify(error)}`);
                  this.setState({
                    smsLoading: false,
                    smsBtnActive: 1,
                  });
                  this.onCodeChange();
                });
            }
          );
        });
      }
    );
  }, 500);

  /**
   * 提交信息登录-短信验证码登录
   * 职责：
   * 1. 验证用户账户密码
   * 2. 通过后初始化用户信息（userId，userName，roleId，token）记录在wStore中
   * 3. 初始化系统权限模块
   * 4. 初始化socket连接
   * 5. 跳转至系统初始页面（先跳转至‘/’，BasicLayout.tsx中再跳转到第一个有权限的菜单页）
   */
  private onSubmitSms = debounce(() => {
    this.setState(
      {
        checkSms: true,
      },
      () => {
        (this.form.current as FormInstance).validateFields().then(async values => {
          const pwd = encryptStr(values.password);
          this.smsForm.current.validateFields().then(async smsValues => {
            this.setState({
              loading: true,
            });

            try {
              const { data } = await loginSms({
                account: values.username,
                pwd,
                smsCaptcha: smsValues.smsCaptcha,
                appCode: 'manager',
              });
              this.checkToResetPwd(data, pwd);
            } catch (error) {
              console.error(`系统异常: ${JSON.stringify(error)}`);
              this.onCodeChange();
            }
            this.setState({
              loading: false,
            });
          });
        });
      }
    );
  }, 500);

  /**提交信息登录-普通登录 */
  private onSubmit = debounce(() => {
    (this.form.current as FormInstance).validateFields().then(async values => {
      const pwd = encryptStr(values.password);
      this.setState({
        loading: true,
      });
      // const history = (this.props as any).history;
      // message.success('登录成功');
      // history.push('/webapp');
      try {
        const { data } = await login({
          account: values.username,
          pwd,
          captcha: values.codeWord,
          captchaId: this.state.codeId,
          appCode: 'manager',
        });
        this.checkToResetPwd(data, pwd);
      } catch (error) {
        console.error(`系统异常: ${JSON.stringify(error)}`);
        this.onCodeChange();
      }
      this.setState({
        loading: false,
      });
    });
  }, 500);

  /**检查是否需要【重置密码】
   * @data-登录接口返回数据
   * @pwd-原始密码-方便修改密码用
   */
  private checkToResetPwd = (data: LoginResponse, pwd: string) => {
    (this.props as JSONObject).setToken(data.token);
    (this.props as JSONObject).setLoginInfo({ ...data, pwd });
    (this.props as JSONObject).setUserInfo({ ...data });

    const history = (this.props as any).history;
    const flag = data.resetPasswordFlag;
    console.log('检测是否需要修改密码****', flag);

    if (flag) {
      // 不需要修改
      (this.props as JSONObject).setSystemConfigAsynic();
      (this.props as JSONObject).setUserInfoLater();

      const store = getStore();
      store.set('firstMenu', {});
      store.save();

      // 权限初始化
      buildMenuPermissionMgr();

      // socket通讯初始化
      setTimeout(() => {
        initSocket();
        checkValidate();
      }, 0);
      message.success('登录成功');
      history.push('/webapp');
    } else {
      history.push('/webapp/resetNewPwd');
    }
  };

  /**检测token是否有效 */
  private checkToken = () => {
    // 如果token有效，直接跳转，无需重新登录
    const history = (this.props as any).history;
    const { token } = this.props as any;
    if (token && token !== '') {
      // token有值，可能是其他页面跳转到登录页面，带有token。
      // 需要请求接口验证token是否有效
      getSysUserInfo()
        .then(res => {
          // token有效
          history.push('/webapp');
        })
        .catch(err => {
          // token无效
          if (process.env.REACT_APP_LOGIN_NO_CHECK != '1') {
            logoutSys();
          }
          this.showLoginBox();
        });
    } else {
      // token无值
      this.showLoginBox();
    }
  };

  /**显示登录区域，切换验证码，聚焦输入框 */
  private showLoginBox = () => {
    this.setState(
      {
        show: true,
      },
      () => {
        document.getElementById('username')?.focus();
        this.onCodeChange();
      }
    );
  };

  /**
   * 获取最新验证码
   */
  private onCodeChange = debounce(() => {
    this.setState(
      {
        codeId: uuidv4(),
      },
      () => {
        this.setState({
          codeImg: `${process.env.REACT_APP_API_URL || ''}/sso/captcha?captchaId=${
            this.state.codeId
          }&timestamp=${+new Date()}`,
        });
      }
    );
  }, 500);

  render() {
    const {
      show,
      codeImg,
      loading,
      checkCode,
      checkSms,
      smsLoading,
      smsBtnActive,
      count,
      showSmsCodeCheck,
    } = this.state;
    const { systemConfig } = this.props as JSONObject;
    const { form, smsForm } = this;
    return (
      <div className="page-login">
        <div className={show ? 'loginBox show' : 'loginBox'}>
          <div className="page-login-title">
            {systemConfig?.systemName || '西安市综合短信发布平台'}
          </div>
          <Form ref={form}>
            <div>
              <Form.Item
                name="username"
                rules={[
                  { max: 15, message: '最大长度为15位字符' },
                  {
                    required: true,
                    whitespace: true,
                    message: '请输入账号',
                  },
                ]}
                getValueFromEvent={event => {
                  return event.target.value.replace(/\s+/g, '');
                }}
              >
                <Input
                  prefix={<UserOutlined style={{ fontSize: 13 }} />}
                  size="large"
                  id="username" // 为了获取焦点
                  placeholder="请输入账号"
                  onPressEnter={this.onSubmit}
                />
              </Form.Item>
              <Form.Item
                name="password"
                rules={[{ required: true, message: '请输入密码' }]}
                getValueFromEvent={event => {
                  return event.target.value.replace(/\s+/g, '');
                }}
              >
                <Input
                  prefix={<KeyOutlined style={{ fontSize: 13 }} />}
                  size="large"
                  id="password" // 为了获取焦点
                  type="password"
                  placeholder="请输入密码"
                  onPressEnter={this.onSubmit}
                />
              </Form.Item>
              <Form.Item>
                <Form.Item
                  name="codeWord"
                  noStyle
                  rules={[{ required: checkCode, message: '请输入图形验证码' }]}
                  getValueFromEvent={event => {
                    // 只能输入英文、数字，长度4位
                    return event.target.value.replace(/[^a-zA-Z0-9]+/g, '').slice(0, 4);
                  }}
                >
                  <Input
                    prefix={<SafetyOutlined style={{ fontSize: 13 }} />}
                    style={{ width: '200px' }}
                    size="large"
                    id="codeWord" // 为了获取焦点
                    maxLength={4}
                    placeholder="图形验证码"
                    onPressEnter={LOGIN_TYPE_SMS ? this.handleSmsCode : this.onSubmit}
                  />
                </Form.Item>
                <Image
                  alt="图形验证码"
                  src={codeImg}
                  height={40}
                  width={140}
                  preview={false}
                  onClick={this.onCodeChange}
                  className="login-code"
                />
              </Form.Item>

              <div style={{ lineHeight: '40px', textAlign: 'center' }}>
                {LOGIN_TYPE_SMS ? (
                  <Button
                    className="submit-btn"
                    size="large"
                    type="primary"
                    loading={smsLoading}
                    disabled={!smsBtnActive}
                    onClick={this.handleSmsCode}
                  >
                    {smsBtnActive
                      ? smsBtnActive > 1
                        ? '重发'
                        : '获取验证码'
                      : '重发(' + count + 's)'}
                  </Button>
                ) : (
                  <Button
                    className="submit-btn"
                    size="large"
                    type="primary"
                    loading={loading}
                    onClick={this.onSubmit}
                  >
                    {loading ? '请稍后' : '登录'}
                  </Button>
                )}
              </div>
            </div>
          </Form>
        </div>
        <Modal
          visible={showSmsCodeCheck}
          footer={null}
          title="短信验证"
          width={400}
          onCancel={() => {
            !loading && this.setState({ showSmsCodeCheck: false });
          }}
        >
          <Form ref={smsForm}>
            <Form.Item>
              <Form.Item
                name="smsCaptcha"
                noStyle
                rules={[{ required: checkSms, message: '请输入短信验证码' }]}
                getValueFromEvent={event => {
                  // 只能输入英文、数字，长度6位
                  return event.target.value.replace(/[^a-zA-Z0-9]+/g, '').slice(0, 6);
                }}
              >
                <Input
                  prefix={<SafetyOutlined style={{ fontSize: 13 }} />}
                  style={{ width: '200px' }}
                  size="large"
                  id="smsCaptcha" // 为了获取焦点
                  maxLength={6}
                  placeholder="短信验证码"
                  onChange={e => {
                    const code = e.target.value;
                    if (code) {
                      this.setState(
                        {
                          checkCode: false,
                        },
                        () => {
                          (this.form.current as FormInstance).validateFields();
                        }
                      );
                    } else {
                      this.setState(
                        {
                          checkCode: true,
                        },
                        () => {
                          (this.form.current as FormInstance).validateFields();
                        }
                      );
                    }
                  }}
                  onPressEnter={this.onSubmitSms}
                />
              </Form.Item>
              <Button
                size="large"
                style={{ width: '140px' }}
                type="primary"
                loading={smsLoading}
                disabled={!smsBtnActive}
                onClick={this.handleSmsCode}
              >
                {smsBtnActive ? (smsBtnActive > 1 ? '重发' : '获取验证码') : '重发(' + count + 's)'}
              </Button>
            </Form.Item>
            <div style={{ lineHeight: '40px', textAlign: 'center' }}>
              <Button
                size="large"
                type="primary"
                loading={loading}
                onClick={this.onSubmitSms}
                style={{ width: 270 }}
              >
                {loading ? '请稍后' : '登录'}
              </Button>
            </div>
          </Form>
        </Modal>
      </div>
    );
  }
}
// state 注入props
const mapStateToProps = (state: JSONObject) => {
  return {
    systemConfig: state.systemConfig,
    token: state.token,
    loginInfo: state.loginInfo,
  };
};
// action 注入props
const mapDispatchToProps = {
  setSystemConfigAsynic,
  setToken,
  setUserInfo,
  setLoginInfo,
  setUserInfoLater,
};

export default connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(
  LoginSms
) as React.ComponentType<RouteConfigComponentProps<any>>;
